package com.yeskery.nut.application;

import com.yeskery.nut.application.bio.BioNutServer;
import com.yeskery.nut.application.jetty.JettyNutServer;
import com.yeskery.nut.application.jetty.JettySecureNutServer;
import com.yeskery.nut.application.netty.NettyNutServer;
import com.yeskery.nut.application.netty.NettySecureNutServer;
import com.yeskery.nut.application.nio.NioNutServer;
import com.yeskery.nut.application.sun.SunNutServer;
import com.yeskery.nut.application.sun.SunSecureNutServer;
import com.yeskery.nut.application.tomcat.TomcatNutServer;
import com.yeskery.nut.application.tomcat.TomcatSecureNutServer;
import com.yeskery.nut.core.BasicNutConfigure;
import com.yeskery.nut.core.NutException;
import com.yeskery.nut.util.ServerUtils;
import com.yeskery.nut.util.StringUtils;

import java.util.logging.Logger;

/**
 * 默认的NutServer构建工厂
 * @author sprout
 * @version 1.0
 * 2022-07-27 18:46
 */
public class DefaultNutServerFactory implements NutServerFactory {

    /** 日志对象 */
    private static final Logger logger = Logger.getLogger(DefaultNutServerFactory.class.getName());

    @Override
    public NutServer buildServer(NutApplication nutApplication, BasicNutConfigure basicNutConfigure) {
        boolean secure = basicNutConfigure.isServerSecurity() != null ? basicNutConfigure.isServerSecurity() : false;
        if (!secure) {
            return doBuildNutServer(ServerUtils.getServerType(basicNutConfigure), null);
        }

        SecureKeyType secureKeyType = basicNutConfigure.getSecureKeyType();

        if (secureKeyType == null) {
            throw new NutException("secureKeyType Must Not Be Null.");
        }

        SecureServerContext secureServerContext = nutApplication.getNutConfigure().getSecureServerContext();
        if (secureKeyType == SecureKeyType.JKS) {
            SecureServerContext jksSecureServerContext = getJksSecureServerContext(basicNutConfigure);
            if (jksSecureServerContext != null) {
                secureServerContext = jksSecureServerContext;
            }
        } else if (secureKeyType == SecureKeyType.PEM) {
            SecureServerContext pemSecureServerContext = getPemSecureServerContext(basicNutConfigure);
            if (pemSecureServerContext != null) {
                secureServerContext = pemSecureServerContext;
            }
        }

        if (secureServerContext == null) {
            throw new NutException("secureServerContext Must Not Be Null.");
        }

        return doBuildNutServer(ServerUtils.getServerType(basicNutConfigure), secureServerContext);
    }

    @Override
    public ServerType getServerType(NutServer nutServer) {
        Class<? extends NutServer> clazz = nutServer.getClass();
        if (JettyNutServer.class.isAssignableFrom(clazz)) {
            return ServerType.JETTY;
        } else if (SunNutServer.class.isAssignableFrom(clazz)) {
            return ServerType.SUN;
        } else if (TomcatNutServer.class.isAssignableFrom(clazz)) {
            return ServerType.TOMCAT;
        } else if (NettyNutServer.class.isAssignableFrom(clazz)) {
            return ServerType.NETTY;
        } else if (BioNutServer.class.isAssignableFrom(clazz)) {
            return ServerType.BIO;
        } else if (NioNutServer.class.isAssignableFrom(clazz)) {
            return ServerType.NIO;
        }
        throw new NutException("Unknown Server Type From [" + clazz.getName() + "]");
    }

    /**
     * 执行构建NutServer服务的方法
     * @param serverType 服务启动类型
     * @param secureServerContext 安全服务上下文
     * @return 构建好的NutServer服务
     */
    private NutServer doBuildNutServer(ServerType serverType, SecureServerContext secureServerContext) {
        if (serverType == ServerType.SUN) {
            return secureServerContext == null ? new SunNutServer() : new SunSecureNutServer(secureServerContext);
        } else if (serverType == ServerType.NETTY) {
            return secureServerContext == null ? new NettyNutServer() : new NettySecureNutServer(secureServerContext);
        } else if (serverType == ServerType.JETTY) {
            return secureServerContext == null ? new JettyNutServer() : new JettySecureNutServer(secureServerContext);
        } else if (serverType == ServerType.TOMCAT) {
            return secureServerContext == null ? new TomcatNutServer() : new TomcatSecureNutServer(secureServerContext);
        } else {
            throw new NutException("UnSupport Server Type [" + serverType + "]");
        }
    }

    /**
     * 获取JKS格式证书安全服务上下文
     * @param basicNutConfigure nut配置信息
     * @return JKS格式证书安全服务上下文
     */
    private SecureServerContext getJksSecureServerContext(BasicNutConfigure basicNutConfigure) {
        String jksPath = basicNutConfigure.getJksPath();
        if (StringUtils.isEmpty(jksPath)) {
            logger.warning("JKS SecureServerContext Miss Required Parameter [jksPath]");
            return null;
        }
        String jksPassword = basicNutConfigure.getJksPassword();
        if (StringUtils.isEmpty(jksPassword)) {
            logger.warning("JKS SecureServerContext Miss Required Parameter [jksPassword]");
            return null;
        }
        return new JksSecureServerContext(jksPath, jksPassword);
    }

    /**
     * 获取PEM格式证书安全服务上下文
     * @param basicNutConfigure nut配置信息
     * @return PEM格式证书安全服务上下文
     */
    private SecureServerContext getPemSecureServerContext(BasicNutConfigure basicNutConfigure) {
        String pemPublicKeyPath = basicNutConfigure.getPemPublicKeyPath();
        if (StringUtils.isEmpty(pemPublicKeyPath)) {
            logger.warning("PEM SecureServerContext Miss Required Parameter [pemPublicKeyPath]");
            return null;
        }

        String pemPrivateKeyPath = basicNutConfigure.getPemPrivateKeyPath();
        if (StringUtils.isEmpty(pemPrivateKeyPath)) {
            logger.warning("PEM SecureServerContext Miss Required Parameter [pemPrivateKeyPath]");
            return null;
        }
        return new PemSecureServerContext(pemPublicKeyPath, pemPrivateKeyPath);
    }
}
